/// LineChart with Label and Gesture Zooming
/// Bugs: when Zooming quickly by clicking between Zoom in and Zoom out Button,
/// the staticTicks don't update timely.
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';

var data1 = [
  new LinearSales(0, "4-12\n16:00", 78),
  new LinearSales(1, '4-13\n16:00', 75),
  new LinearSales(2, '4-14\n16:00', 100),
  new LinearSales(3, '4-15\n16:00', 25),
  new LinearSales(4, '4-16\n16:00', 5),
];

var data2 = [
  new LinearSales(0, '4-14\n16:00', 75),
  new LinearSales(1, '4-15\n04:00', 75),
  new LinearSales(2, '4-15\n16:00', 99),
  new LinearSales(3, '4-16\n04:00', 55),
  new LinearSales(4, '4-16\n16:00', 25),
];

var data3 = [
  new LinearSales(0, '4-15\n08:00', 78),
  new LinearSales(1, '4-15\n16:00', 75),
  new LinearSales(2, '4-16\n00:00', 100),
  new LinearSales(3, '4-16\n08:00', 25),
  new LinearSales(4, '4-16\n16:00', 5),
];

var data4 = [
  new LinearSales(0, '4-15\n16:00', 75),
  new LinearSales(1, '4-15\n22:00', 75),
  new LinearSales(2, '4-16\n04:00', 99),
  new LinearSales(3, '4-16\n10:00', 55),
  new LinearSales(4, '4-16\n16:00', 25),
];

var data5 = [
  new LinearSales(0, '4-15\n20:48', 78),
  new LinearSales(1, '4-16\n01:46', 75),
  new LinearSales(2, '4-16\n06:24', 100),
  new LinearSales(3, '4-16\n11:12', 25),
  new LinearSales(4, '4-16\n16:00', 5),
];

var data = [
  data1,
  data2,
  data3,
  data4,
  data5,
];

void main() {
  runApp(MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.fallback(),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Chart Demo'),
        ),
        body: PointsLineChart(),
      )
  ));
}

class PointsLineChart extends StatefulWidget {
  @override
  PointsLineChartState createState() => PointsLineChartState();
}

class PointsLineChartState extends State<PointsLineChart> {

  int index = 0;
  int previousIndex;
  bool isZooming = false;
  List<LinearSales> tsdata = data[0];

  Widget chartWidget() {
    var series = [
      new charts.Series<LinearSales, int>(
        id: 'Sales',
        colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
        domainFn: (LinearSales sales, _) => sales.index,
        measureFn: (LinearSales sales, _) => sales.sales,
        data: tsdata,
      )
    ];

    // Create the ticks to be used the domain axis.
    final staticTicks = <charts.TickSpec<int>>[
      new charts.TickSpec(
        // Value must match the domain value.
        0,
        // Optional label for this tick, defaults to domain value if not set.
        label: tsdata[0].dataTime,
      ),
      // If no text style is specified - the style from renderSpec will be used
      // if one is specified.
      new charts.TickSpec(
        // Value must match the domain value.
        1,
        // Optional label for this tick, defaults to domain value if not set.
        label: tsdata[1].dataTime,
      ),
      new charts.TickSpec(
        // Value must match the domain value.
        2,
        // Optional label for this tick, defaults to domain value if not set.
        label: tsdata[2].dataTime,
      ),
      new charts.TickSpec(
        // Value must match the domain value.
        3,
        // Optional label for this tick, defaults to domain value if not set.
        label: tsdata[3].dataTime,
      ),
      new charts.TickSpec(
        // Value must match the domain value.
        4,
        // Optional label for this tick, defaults to domain value if not set.
        label: tsdata[4].dataTime,
      ),
    ];

    var chart = new charts.LineChart(series,
      animate: false,
      animationDuration: const Duration(milliseconds: 300),
      defaultRenderer: new charts.LineRendererConfig(includePoints: true),
      domainAxis: new charts.NumericAxisSpec(
        tickProviderSpec:
          new charts.StaticNumericTickProviderSpec(staticTicks)
      ),
      behaviors: [
        new charts.LinePointHighlighter(
          showHorizontalFollowLine:
          charts.LinePointHighlighterFollowLineType.none,
          showVerticalFollowLine:
          charts.LinePointHighlighterFollowLineType.nearest,
        ),
      ],
    );

    return Container(
      height: 350,
      padding: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
      child: new Card(
        child: GestureDetector(
          onScaleStart: (scaleDetails) {
            isZooming = true;
          },
          onScaleUpdate: (ScaleUpdateDetails scaleDetails) {
            debugPrint("scale details:" + scaleDetails.toString());
            if (isZooming) {
              setState(() {
                isZooming = false;
                if (scaleDetails.scale > 1) {
                  index = index + 1;
                  if (index > 4) index = 4;
                  debugPrint("current index: $index");
                  tsdata = data[index];
                } else if (scaleDetails.scale < 1) {
                  index = index - 1;
                  if (index < 0) index = 0;
                  debugPrint("current index: $index");
                  tsdata = data[index];
                }
              });
            }
          },
          onScaleEnd: (scaleDetails) {
            isZooming = false;
          },
          child: Padding(
            padding: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 10.0),
            child: chart,
          ),
        )
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Row(
          children: [
            new Expanded(
              child: chartWidget(),
            ),
          ],
        ),
        SizedBox(
          height: 35.0,
        ),
        Text('Current level ${index + 1}',
          style: TextStyle(fontSize: 22, fontWeight: FontWeight.w700)),
        SizedBox(
          height: 35.0,
        ),
        RaisedButton(
          onPressed: () {
            setState(() {
              index = index + 1;
              if (index > 4) index = 4;
              debugPrint("current index: $index");
              tsdata = data[index];
            });
          },
          child: Text('Zoom in'),
        ),
        RaisedButton(
          onPressed: () {
            setState(() {
              index = index - 1;
              if (index < 0) index = 0;
              debugPrint("current index: $index");
              tsdata = data[index];
            });
          },
          child: Text('Zoom out'),
        ),
      ],
    );
  }
}

/// Sample linear data type.
class LinearSales {
  final int index;
  final String dataTime;
  final int sales;

  LinearSales(this.index, this.dataTime, this.sales);
}
